#!/bin/bash

# Adapted from Pivotals libhdfs3 native c++ hdfs client project
# https://github.com/Pivotal-Data-Attic/pivotalrd-libhdfs3

die() {
    echo "$@" 1>&2 ; exit 1
}

arg() {
    echo "$1" | sed "s/^${2-[^=]*=}//" | sed "s/:/;/g"
}

# Detect directory information.
source_dir=`cd "\`dirname \"$0\"\`";pwd`
binary_dir=`pwd`

# Choose the default install prefix.
default_prefix="${binary_dir}/dist"

# Choose the default dependency install prefix
default_dependency=${DEPENDENCY_INSTALL_PREFIX}

if [ x"${default_dependency}" = x"" ]; then
    default_dependency="/opt/dependency"
fi

# Display bootstrap usage
usage() {
echo '
Usage: '"$0"' [<options>]
Options: [defaults in brackets after descriptions]
Configuration:
    --help                          print this message
    --prefix=PREFIX                 install files in tree rooted at PREFIX
                                    ['"${default_prefix}"']
    --vcpkg-base-triplet=TRIPLET    vcpkg base triplet to use when building with sanitizers
    --dependency=DIRs               specify the dependencies at DIRs, separated by colon
                                    ['"${default_dependency}"']
    --linkage                       specify the linkage of tiledb. Defaults to shared.
                                    [static|shared]
    --remove-deprecations           build TileDB without any deprecated APIs
    --disable-werror                disables use of -Werror during build
    --disable-cpp-api               disables building of the TileDB C++ API
    --disable-tests                 disables building the TileDB tests
    --disable-stats                 disables internal TileDB statistics
    --disable-avx2                  disables use of AVX2 instructions
    --disable-webp                  disables building of webp library
    --enable-rust                   enable building Rust tests
    --enable-static-tiledb          enables building TileDB as a static library (deprecated, use --linkage=static)
    --enable-sanitizer=SAN          enable sanitizer (clang only)
                                    (address|memory|leak|thread|undefined)
                                    Must manually specify a vcpkg base triplet.
    --enable-debug                  enable debug build
    --enable-assertions             enable assertions in compiled code
    --enable-release-symbols        enable create symbols for release build
    --enable-coverage               enable build with code coverage support
    --enable-verbose                enable verbose status messages
    --enable-hdfs                   enables the hdfs storage backend
    --enable-s3                     enables the s3 storage backend
    --enable-azure                  enables the azure storage backend
    --enable-gcs                    enables the gcs storage backend
    --enable-serialization          enables query serialization support
    --enable-ccache                 enables use of ccache (if present)
    --enable-arrow-tests            enables the compilation of the arrow adapter unit tests
    --enable-aws-s3-config          enables AWS S3 configuration for tests
    --enable=arg1,arg2...           same as "--enable-arg1 --enable-arg2 ..."


Dependencies:
    c/c++ compiler
    GNU make
    cmake           http://www.cmake.org/

Example:
    mkdir build
    cd build
    ../bootstrap --prefix=/path/to/install --dependency=/path/to/dep1:path/to/dep2...
    make
    make install
'
    exit 10
}

# Parse arguments
prefix_dirs="${default_prefix}"
vcpkg_base_triplet=""
dependency_dir="${default_dependency}"
sanitizer=""
build_type="Release"
tiledb_verbose="OFF"
tiledb_hdfs="OFF"
tiledb_s3="OFF"
tiledb_azure="OFF"
tiledb_gcs="OFF"
tiledb_werror="ON"
tiledb_tests="ON"
tiledb_cpp_api="ON"
tiledb_remove_deprecations="OFF"
tiledb_stats="ON"
build_shared_libs="OFF"
tiledb_disable_avx2=""
tiledb_assertions="OFF"
tiledb_serialization="OFF"
tiledb_tools="OFF"
tiledb_ccache="OFF"
tiledb_arrow_tests="OFF"
tiledb_experimental_features="OFF"
tiledb_build_webp="ON"
tiledb_build_rust="OFF"
tiledb_tests_aws_s3_config="OFF"
enable_multiple=""
while test $# != 0; do
    case "$1" in
    --prefix=*) dir=`arg "$1"`
                prefix_dirs="$dir";;
    --vcpkg-base-triplet=*)   vcpkg_base_triplet=`arg "$1"`
                                vcpkg_base_triplet="-DTILEDB_VCPKG_BASE_TRIPLET=${vcpkg_base_triplet}";;
    --dependency=*) dir=`arg "$1"`
                dependency_dir="$dir";;
    --linkage=*) linkage=`arg "$1"`;;
    --force-build-all-deps) echo "Argument '--force-build-all-deps' has no effect and will be removed in a future version. Vcpkg builds all dependencies by default, please consult the guide in doc/main/BUILD.md or vcpkg's documentation to see how to provide your own dependencies.";;
    --remove-deprecations) tiledb_remove_deprecations="ON";;
    --disable-werror) tiledb_werror="OFF";;
    --disable-tests) tiledb_tests="OFF";;
    --disable-cpp-api) tiledb_cpp_api="OFF";;
    --disable-stats) tiledb_stats="OFF";;
    --disable-avx2) tiledb_disable_avx2="-DCOMPILER_SUPPORTS_AVX2=FALSE";;
    --disable-webp) tiledb_build_webp="OFF";;
    --enable-rust) tiledb_build_rust="ON";;
    --enable-assertions) tiledb_assertions="ON";;
    --enable-debug) build_type="Debug";;
    --enable-release-symbols) build_type="RelWithDebInfo";;
    --enable-coverage) build_type="Coverage";;
    --enable-verbose) tiledb_verbose="ON";;
    # TODO: Completely remove the switch. Let's keep it for a while to cause configuration failures that will let users know that HDFS is no longer supported.
    --enable-hdfs) tiledb_hdfs="ON";;
    --enable-s3) tiledb_s3="ON";;
    --enable-azure) tiledb_azure="ON";;
    --enable-gcs) tiledb_gcs="ON";;
    --enable-serialization) tiledb_serialization="ON";;
    --enable-static-tiledb) echo "Argument '--enable-static-tiledb' is obsolete and will be removed in a future version. Use --linkage=static instead."
                            enable_static_tiledb="ON";;
    --enable-sanitizer=*) san=`arg "$1"`
                sanitizer="$san";;
    --enable-tools) tiledb_tools="ON";;
    --enable-ccache) tiledb_ccache="ON";;
    --enable-arrow-tests) tiledb_arrow_tests="ON";;
    --enable-aws-s3-config) tiledb_tests_aws_s3_config="ON";;
    --enable=*) s=`arg "$1"`
                enable_multiple+="${enable_multiple:+,}${s}";;
    --help) usage ;;
    *) die "Unknown option: $1" ;;
    esac
    shift
done

# Parse the comma-separated list of enables.
IFS=',' read -ra enables <<< "$enable_multiple"
for en in "${enables[@]}"; do
  case "$en" in
    assertions) tiledb_assertions="ON";;
    debug) build_type="Debug";;
    release-symbols) build_type="RelWithDebInfo";;
    coverage) build_type="Coverage";;
    verbose) tiledb_verbose="ON";;
    s3) tiledb_s3="ON";;
    azure) tiledb_azure="ON";;
    gcs) tiledb_gcs="ON";;
    serialization) tiledb_serialization="ON";;
    tools) tiledb_tools="ON";;
    ccache) tiledb_ccache="ON";;
    arrow-tests) tiledb_arrow_tests="ON";;
    hdfs) tiledb_hdfs="ON";;
    static-tiledb) echo "Argument '--enable-static-tiledb' is obsolete and will be removed in a future version. Use --linkage=static instead."
                    enable_static_tiledb="ON";;
    aws-s3-config) tiledb_tests_aws_s3_config="ON";;
    rust) tiledb_build_rust="ON";;
    *) die "Unknown option: --enable-$en" ;;
  esac
done

if [ "${source_dir}" = "${binary_dir}" ]; then
    die "cannot build the project in the source directory! Out-of-source build is enforced!"
fi

if [ "${linkage}" = "shared" ] || [ "${linkage}" = "" ]; then
    build_shared_libs="ON"
elif [ "${linkage}" = "static" ] || [ "${enable_static_tiledb}" = "ON" ]; then
    build_shared_libs="OFF"
else
    die "unknown linkage: ${linkage}"
fi

# Fail if both --linkage=shared and --enable-static-tiledb are specified
if [ "${linkage}" = "shared" ] && [ "${enable_static_tiledb}" = "ON" ]; then
    die "cannot specify both --linkage=shared and --enable-static-tiledb"
fi

# Configure
cmake -DCMAKE_BUILD_TYPE=${build_type} \
    -DCMAKE_INSTALL_PREFIX="${prefix_dirs}" \
    -DCMAKE_PREFIX_PATH="${dependency_dir}" \
    -DBUILD_SHARED_LIBS=${build_shared_libs} \
    -DTILEDB_ASSERTIONS=${tiledb_assertions} \
    -DTILEDB_VERBOSE=${tiledb_verbose} \
    -DTILEDB_HDFS=${tiledb_hdfs} \
    -DTILEDB_S3=${tiledb_s3} \
    -DTILEDB_AZURE=${tiledb_azure} \
    -DTILEDB_GCS=${tiledb_gcs} \
    -DTILEDB_SERIALIZATION=${tiledb_serialization} \
    -DTILEDB_TOOLS=${tiledb_tools} \
    -DTILEDB_WERROR=${tiledb_werror} \
    -DTILEDB_CPP_API=${tiledb_cpp_api} \
    -DTILEDB_STATS=${tiledb_stats} \
    -DTILEDB_TESTS=${tiledb_tests} \
    -DTILEDB_CCACHE=${tiledb_ccache} \
    -DTILEDB_ARROW_TESTS=${tiledb_arrow_tests} \
    -DTILEDB_WEBP=${tiledb_build_webp} \
    -DTILEDB_RUST=${tiledb_build_rust} \
    -DTILEDB_REMOVE_DEPRECATIONS=${tiledb_remove_deprecations} \
    -DTILEDB_SANITIZER="${sanitizer}" \
    -DTILEDB_EXPERIMENTAL_FEATURES=${tiledb_experimental_features} \
    -DTILEDB_TESTS_AWS_S3_CONFIG=${tiledb_tests_aws_s3_config} \
    ${tiledb_disable_avx2} \
    ${vcpkg_base_triplet} \
    "${source_dir}" || die "failed to configure the project"

echo 'bootstrap success. Run "make" to build, "make check" to test, or "make install" to install.'
